{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Try GRASS GIS in Jupyter Notebook with Python\n",
    "\n",
    "[<img src=\"../../man/grass_logo.png\" alt=\"GRASS GIS\" style=\"width:200px;\"/>](https://grass.osgeo.org/)\n",
    "\n",
    "This is a quick introduction to *GRASS GIS* in a *Jupyter Notebook* using the *Python* scripting language.\n",
    "The interactive notebook is available online thanks to the [*Binder*](https://mybinder.org/) service.\n",
    "\n",
    "Examples here are using a sample GRASS GIS dataset for North Carolina, USA. The dataset is included in this environment.\n",
    "\n",
    "## Usage\n",
    "\n",
    "To run the selected part which is called a cell, hit `Shift + Enter`.\n",
    "\n",
    "## Start\n",
    "\n",
    "There are several ways to use GRASS GIS. When using Python in a notebook, we usually find GRASS GIS Python packages first, import them, initialize GRASS GIS session, and set several variables useful for using GRASS GIS in a notebook."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import Python standard library and IPython packages we need.\n",
    "import os\n",
    "import sys\n",
    "import subprocess\n",
    "from IPython.display import Image\n",
    "\n",
    "# Ask GRASS GIS where its Python packages are.\n",
    "gisbase = subprocess.check_output([\"grass\", \"--config\", \"path\"], text=True).strip()\n",
    "os.environ['GISBASE'] = gisbase\n",
    "sys.path.append(os.path.join(gisbase, \"etc\", \"python\"))\n",
    "\n",
    "# Import the GRASS GIS packages we need.\n",
    "import grass.script as gs\n",
    "import grass.script.setup as gsetup\n",
    "\n",
    "# Create a GRASS GIS session.\n",
    "rcfile = gsetup.init(gisbase, \"../../data/grassdata\", \"nc_basic_spm_grass7\", \"user1\")\n",
    "\n",
    "# We want functions to raise exceptions and see standard output of the modules in the notebook.\n",
    "gs.set_raise_on_error(True)\n",
    "gs.set_capture_stderr(True)\n",
    "# Simply overwrite existing maps like we overwrite Python variable values.\n",
    "os.environ['GRASS_OVERWRITE'] = '1'\n",
    "# Enable map rendering in a notebook.\n",
    "os.environ['GRASS_FONT'] = 'sans'\n",
    "# Set display modules to render into a file (named map.png by default)\n",
    "os.environ['GRASS_RENDER_IMMEDIATE'] = 'cairo'\n",
    "os.environ['GRASS_RENDER_FILE_READ'] = 'TRUE'\n",
    "os.environ['GRASS_LEGEND_FILE'] = 'legend.txt'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Raster buffer\n",
    "\n",
    "Set computational region and create multiple buffers in given distances\n",
    "around lakes represented as raster:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gs.parse_command('g.region', raster=\"lakes\", flags='pg')\n",
    "gs.run_command('r.buffer', input=\"lakes\", output=\"lakes_buff\", distances=[60, 120, 240, 500])\n",
    "gs.run_command('d.erase')\n",
    "gs.run_command('d.rast', map=\"lakes_buff\")\n",
    "gs.run_command('d.legend', raster=\"lakes_buff\", range=(2, 5), at=(80, 100, 2, 10))\n",
    "Image(filename=\"map.png\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Vector buffer\n",
    "\n",
    "Create a negative buffer around state boundary represented as a vector.\n",
    "Vector modules typically don't follow computational region,\n",
    "but we set it to inform display modules about our area of interest."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gs.run_command('v.buffer', input=\"boundary_state\", output=\"buffer\", distance=-10000)\n",
    "gs.parse_command('g.region', vector=\"boundary_state\", flags='pg')\n",
    "gs.run_command('d.erase')  # erase the display before drawing again\n",
    "!rm -f $GRASS_LEGEND_FILE  # and remove the legend file\n",
    "gs.run_command('d.vect', map=\"boundary_state\", fill_color=\"#5A91ED\", legend_label=\"State boundary\")\n",
    "gs.run_command('d.vect', map=\"buffer\", fill_color=\"#F8766D\", legend_label=\"Inner portion\")\n",
    "gs.run_command('d.legend.vect', at=(10, 35))\n",
    "Image(filename=\"map.png\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Additional GRASS Information and Tutorials\n",
    "\n",
    "To find more information on what one can do with GRASS GIS APIs, check out:\n",
    "    \n",
    " - [GRASS GIS Manual](https://grass.osgeo.org/grass-stable/manuals)\n",
    "    \n",
    " - [GRASS Python API Manual](https://grass.osgeo.org/grass-stable/manuals/libpython)\n",
    "\n",
    "For more Jupyter Notebook GRASS GIS tutorials, visit:\n",
    " - [Try GRASS GIS online](https://grass.osgeo.org/learn/tryonline/)\n",
    "\n",
    "## What else is in the sample North Carolina dataset?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(gs.read_command(\"g.list\", type=\"all\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## What other GRASS modules can I try in this notebooks?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(gs.read_command(\"g.search.modules\", flags=\"g\"))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
